package com.ocom.company.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.ocom.common.constant.CompanyServiceUrl;
import com.ocom.common.entity.company.EntityFlowApprover;
import com.ocom.common.entity.company.EntityFlowConfig;
import com.ocom.common.entity.human.EntityBizApply;
import com.ocom.common.entity.human.EntityBizLeaveApply;
import com.ocom.common.entity.human.EntityDeptInfo;
import com.ocom.common.entity.human.EntityPersonnelInfo;
import com.ocom.common.entity.master.EntityMngUserInfo;
import com.ocom.common.enums.ResultEnum;
import com.ocom.common.request.activiti.ApplySaveRequest;
import com.ocom.common.request.activiti.HandleTasksRequest;
import com.ocom.common.request.activiti.PendingTasksRequest;
import com.ocom.common.request.company.*;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.ResultUtil;
import com.ocom.common.vo.FlowPushInfoVo;
import com.ocom.common.vo.GetFlowPushByLineVo;
import com.ocom.common.vo.activiti.IncompleteTaskVO;
import com.ocom.common.vo.activiti.PageResultVo;
import com.ocom.common.vo.company.*;
import com.ocom.company.feign.ActivitiClientService;
import com.ocom.company.feign.HumanClient;
import com.ocom.company.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
public class FlowController {

    @Autowired
    private PersonnelInfoService personnelInfoService;

    @Autowired
    private FlowConfigService flowConfigService;

    @Autowired
    private FlowApproverService flowApproverService;

    @Autowired
    private HumanClient humanClientService;

    @Autowired
    private FlowPushInfoService flowPushInfoService;

    @Autowired
    private ActivitiClientService activitiClientService;

    @Autowired
    BizApplyService bizApplyService;

    @Autowired
    BizLeaveApplyService bizLeaveApplyService;

    @Autowired
    private MngUserInfoService mngUserInfoService;
    @PostMapping(CompanyServiceUrl.URL_getFlowkeyByPid)
    public Result getFlowkeyByPid(@RequestBody GetFlowkeyByPidRequest getFlowkeyByPidRequest){
        List<EntityFlowConfig>  entityFlowConfigList = this.flowConfigService.getFlowConfig(getFlowkeyByPidRequest.getComId(),getFlowkeyByPidRequest.getFlowCode(),-10);
        if(ObjectUtil.isEmpty(entityFlowConfigList)){
            return ResultUtil.error(ResultEnum.Err_5001);
        }
        PersonnelInfoVo personnelInfo = this.personnelInfoService.getPersonnelInfoByPid(getFlowkeyByPidRequest.getComId(),getFlowkeyByPidRequest.getPId());

        if(ObjectUtil.isEmpty(personnelInfo)){
            return ResultUtil.error(ResultEnum.Err_303);
        }

        EntityFlowConfig flowConfig = null;
        for (EntityFlowConfig config:entityFlowConfigList){
            if(config.getDeptType() < -1 || config.getDeptType().equals(personnelInfo.getDeptType())){
                flowConfig = config;
                break;
            }
        }
        if(ObjectUtil.isEmpty(flowConfig)){
            return ResultUtil.error(ResultEnum.Err_5001);
        }
        List<EntityFlowApprover> approverList = this.flowApproverService.getByFid(getFlowkeyByPidRequest.getComId(),flowConfig.getFlowId());
        //获取变量信息
        Map<String,Object> varMap = new LinkedHashMap<>();
        varMap.put("assignee0",getFlowkeyByPidRequest.getComId()+"P"+getFlowkeyByPidRequest.getPId());
        if(ObjectUtil.isNotEmpty(approverList)){
            for(EntityFlowApprover approver:approverList){
                //管理员
                if(1 == approver.getType()){
                    varMap.put(approver.getVarTag(),approver.getIds());
                }else if(2 ==approver.getType() ){
                    //管理员角色
                    String[] roleIds = approver.getIds().split(",");
                    List<String> ids = new ArrayList<>();
                    for (String roleId: roleIds){
                        List<EntityMngUserInfo> entityMngUserInfoList = mngUserInfoService.getUserByRole(getFlowkeyByPidRequest.getComId(),Long.valueOf(roleId),personnelInfo.getDeptId().longValue());
                        for (EntityMngUserInfo userInfo: entityMngUserInfoList) {
                            ids.add(userInfo.getId().toString());
                        }
                    }
                    if(ObjectUtil.isEmpty(ids)){
                        return ResultUtil.error(ResultEnum.Err_5002);
//                        throw new RuntimeException(String.format("变量名【%s】请配置管理员",approver.getVarTag()));
                    }
                    varMap.put(approver.getVarTag(),String.join(",", ids));

                }else if(3 == approver.getType()){
                    //人员
                    varMap.put(approver.getVarTag(),approver.getIds());
                }

            }
        }
        FlowConfigVo flowConfigVo = new FlowConfigVo();
        flowConfigVo.setDefKey(flowConfig.getApplyKey());
        flowConfigVo.setDeptId(personnelInfo.getDeptId());
        flowConfigVo.setDeptName(personnelInfo.getDeptName());
        flowConfigVo.setPName(personnelInfo.getPName());
        flowConfigVo.setVariables(varMap);

        return ResultUtil.success(flowConfigVo);
    }


    //根据线程路线获取推送人
    @PostMapping(CompanyServiceUrl.URL_getPushByLine)
    public Result getPushByLine(@RequestBody GetPushByLineRequest getPushByLineRequest){
        //分解关键字格式  关键字:单位ID:申请ID
        String[] strings = getPushByLineRequest.getBusinessKey().split(":");
        if(strings.length != 3){
            throw new RuntimeException("businessKey错误");
        }
        String busineeeKey = strings[0];
        Long companyId = Long.valueOf(strings[1]);
        Long applyId = Long.valueOf(strings[2]);
        EntityBizApply entityBizApply = new EntityBizApply();
        entityBizApply.setBusinessId(applyId);
        entityBizApply.setComId(companyId);
//        Result<EntityBizApply> entityBizApplyResult = this.humanClientService.applyOne(entityBizApply);
//        entityBizApply = entityBizApplyResult.getData();
        entityBizApply = bizApplyService.getApplyOne(entityBizApply.getComId(),entityBizApply);
//        log.info("申请事项【{}】", JSON.toJSONString(entityBizApplyResult));
        if(ObjectUtil.isEmpty(entityBizApply)){
            throw new RuntimeException("申请事项不存在");
        }
        //获取人员信息
        EntityPersonnelInfo entityPersonnelInfo = personnelInfoService.getPerInfo(companyId,entityBizApply.getPId());
        if(ObjectUtil.isEmpty(entityPersonnelInfo)){
            throw new RuntimeException("申请人不存在");
        }
        EntityDeptInfo entityDeptInfo = new EntityDeptInfo();
        entityDeptInfo.setDeptId(entityPersonnelInfo.getDeptId());
        entityDeptInfo.setComId(companyId);
        Result<EntityDeptInfo> entityDeptInfoResult = this.humanClientService.getDeptById(entityDeptInfo);
        entityDeptInfo = entityDeptInfoResult.getData();
        log.info("部门信息【{}】", JSON.toJSONString(entityDeptInfoResult));
        if(ObjectUtil.isEmpty(entityDeptInfo)){
            throw new RuntimeException("部门信息不存在");
        }
        SelectFlowPushInfoRequest selectFlowPushInfoRequest = new SelectFlowPushInfoRequest();
        selectFlowPushInfoRequest.setFlowKeyword(busineeeKey);
        selectFlowPushInfoRequest.setLineId(getPushByLineRequest.getLineId());
        List<FlowPushInfoVo> flowPushInfoList = this.flowPushInfoService.selectFlowPushInfo(companyId,selectFlowPushInfoRequest);
        if(ObjectUtil.isEmpty(flowPushInfoList)){
            throw new RuntimeException("推送人信息不存在");
        }

        GetFlowPushByLineVo getFlowPushByLineVo = new GetFlowPushByLineVo();
        getFlowPushByLineVo.setPName(entityPersonnelInfo.getPName());
        getFlowPushByLineVo.setDeptName(entityDeptInfo.getDeptName());
        getFlowPushByLineVo.setApplyTime(entityBizApply.getApplyTime());
        getFlowPushByLineVo.setFlowName(flowPushInfoList.get(0).getFlowName());
        getFlowPushByLineVo.setContent(flowPushInfoList.get(0).getContent());
        getFlowPushByLineVo.setBusinessId(applyId);
        getFlowPushByLineVo.setComId(companyId);
        Set<Long> userIds = new HashSet<>();
        Map<Long,String> userMessage = new HashMap<>();
        for(FlowPushInfoVo flowPushInfoVo: flowPushInfoList){
            if(1 == flowPushInfoVo.getType()){
                stringToSet(userIds,userMessage, flowPushInfoVo.getIds(), ",",flowPushInfoVo.getContent());
            }else if(2 ==flowPushInfoVo.getType() ){
                //管理员角色
                String[] roleIds = flowPushInfoVo.getIds().split(",");
                for (String roleId: roleIds){
                    List<EntityMngUserInfo> entityMngUserInfoList = mngUserInfoService.getUserByRole(companyId,Long.valueOf(roleId),entityDeptInfo.getDeptId());
                    for (EntityMngUserInfo userInfo: entityMngUserInfoList) {
                        userIds.add(userInfo.getId());
                    }
                }
            }else if(3 == flowPushInfoVo.getType()){
                //人员
                stringToSet(userIds,userMessage, flowPushInfoVo.getIds(), ",",flowPushInfoVo.getContent());
            }
        }
        List<GetFlowPushByLineVo.PushInfo> pushInfoList = new ArrayList<>();
        if(ObjectUtil.isNotEmpty(userIds)){
            List<EntityMngUserInfo> entityMngUserInfoList = this.mngUserInfoService.getMngUserList(Lists.newArrayList(userIds));

            entityMngUserInfoList.forEach(entityMngUserInfo -> {
                GetFlowPushByLineVo.PushInfo pushInfo = new GetFlowPushByLineVo.PushInfo();
                pushInfo.setPushName(entityMngUserInfo.getUserName());
                pushInfo.setPhone(entityMngUserInfo.getPhone());
                pushInfo.setId(entityMngUserInfo.getId().toString());
                pushInfoList.add(pushInfo);
            });
        }
        getFlowPushByLineVo.setPushList(pushInfoList);

        //获取最后审批人姓名
        if(ObjectUtil.isNotEmpty(entityBizApply.getLastApprovalUser()) ){
            if(entityBizApply.getLastApprovalUser().toUpperCase().contains("P")){
                String[] lastApprovalUsers = entityBizApply.getLastApprovalUser().toUpperCase().split("P");
                if(lastApprovalUsers.length != 2){ throw new RuntimeException("最后审批人信息错误"); }

                EntityPersonnelInfo personnelInfo = this.personnelInfoService.getPerInfo(companyId,Long.valueOf(lastApprovalUsers[1]));
                if(ObjectUtil.isNotEmpty(personnelInfo)){
                    getFlowPushByLineVo.setApproverName(personnelInfo.getPName());
                }
            }else{
                EntityMngUserInfo entityMngUserInfo = this.mngUserInfoService.GetMngUserInfo(Long.valueOf(entityBizApply.getLastApprovalUser()));
                if(ObjectUtil.isNotEmpty(entityMngUserInfo)){
                    getFlowPushByLineVo.setApproverName(entityMngUserInfo.getUserName());
                }
            }
        }

        //获取流程配置
        return ResultUtil.success(getFlowPushByLineVo);
    }

    @PostMapping(CompanyServiceUrl.URL_getFlowInstanceList)
    public Result getFlowInstanceList(@RequestBody GetFlowInstanceListRequest getFlowInstanceListRequest){
        Page<GetFlowInstanceListVo> page = this.flowConfigService.getFlowInstanceList(getFlowInstanceListRequest.getComId(),getFlowInstanceListRequest);
        Map<String, Object> map = new HashMap<>();
        map.put("list",page.getRecords());
        map.put("total",page.getTotal());
        return ResultUtil.success(map);
    }

    @PostMapping(CompanyServiceUrl.URL_getApplyTasks)
    public Result getApplyTasks(@RequestBody GetApplyTasksRequest getApplyTasksRequest){
        String userId = getApplyTasksRequest.getUserId().toString();
        if(ObjectUtil.isEmpty(getApplyTasksRequest.getUserId())){
            if(ObjectUtil.isEmpty(getApplyTasksRequest.getPId())){
                return ResultUtil.error(ResultEnum.Err_5005);
            }else{
                userId = String.format("%sP%s",getApplyTasksRequest.getComId(),getApplyTasksRequest.getPId());
            }
        }

        PendingTasksRequest pendingTasksRequest = new PendingTasksRequest();
        pendingTasksRequest.setUserId(userId);
        Result<PageResultVo<IncompleteTaskVO>> result = this.activitiClientService.pendingTasks(pendingTasksRequest);
        if(result.getData().getTotal() == 0){
            return ResultUtil.error(ResultEnum.Err_5006);
        }

        List<Integer> businessKeys = result.getData().getRows().stream().map(IncompleteTaskVO::getBusinessKeyId).collect(Collectors.toList());
        List<FlowInstanceInfoVo>  flowInstanceInfoVoList = this.flowConfigService.flowInstanceInfoList(getApplyTasksRequest.getComId(), businessKeys);
        for (FlowInstanceInfoVo flowInstanceInfoVo:flowInstanceInfoVoList){
            for (IncompleteTaskVO  incompleteTaskVO:result.getData().getRows()){
                if(incompleteTaskVO.getBusinessKeyId().equals(flowInstanceInfoVo.getBusinessId())){
                    flowInstanceInfoVo.setTaskName(incompleteTaskVO.getTaskName());
//                    flowInstanceInfoVo.setStartTime(incompleteTaskVO.getStartTime());
                    flowInstanceInfoVo.setTaskId(incompleteTaskVO.getId());
                }
            }
        }
        return ResultUtil.success(flowInstanceInfoVoList);
    }


    @PostMapping(CompanyServiceUrl.URL_handleApply)
    public Result handleApply(@RequestBody HandleApplyRequest applyRequest){
        HandleTasksRequest applySaveRequest = Convert.convert(HandleTasksRequest.class,applyRequest);
//        applySaveRequest.setParams(JSON.parseObject(applyRequest.getParams(),HashMap.class));
        Result<HashMap> resultExit = this.activitiClientService.handleTask(applySaveRequest);
        if(resultExit.getCode() != 200){
            return ResultUtil.error(ResultEnum.Err_5009);
        }

        Boolean exit = (Boolean)resultExit.getData().get("exit");
        if(exit.equals(Boolean.TRUE)) {
            EntityBizApply entityBizApply = new EntityBizApply();
            entityBizApply.setBusinessId(applyRequest.getBusinessId());
            entityBizApply.setStatus(applyRequest.getStatus());
            entityBizApply.setComId(applyRequest.getComId());
            entityBizApply.setLastApprovalUser(applyRequest.getUserName());
            entityBizApply.setLastApprovalTime(new Date());
            this.bizApplyService.update(entityBizApply.getComId(), entityBizApply);

            EntityBizLeaveApply entityBizLeaveApply=new EntityBizLeaveApply();
            entityBizLeaveApply.setId(applyRequest.getBusinessId());
            entityBizLeaveApply.setStatus(applyRequest.getStatus());
            entityBizLeaveApply.setComId(applyRequest.getComId());
            this.bizLeaveApplyService.update(applyRequest.getComId(),entityBizLeaveApply);
        }
        return ResultUtil.success();
    }

    @PostMapping(CompanyServiceUrl.URL_newApply)
    public Result newApply(@RequestBody NewApplyRequest applyRequest){
        ApplySaveRequest applySaveRequest = new ApplySaveRequest();
        applySaveRequest.setApplyId(applyRequest.getComId()+":"+applyRequest.getBusinessId());
        applySaveRequest.setApplyUser(applyRequest.getPId().toString());
        applySaveRequest.setApplyKey(applyRequest.getDefKey());
        applySaveRequest.setParams(applyRequest.getParams());
        applySaveRequest.setVariables(applyRequest.getVariables());
        Result<Map<String,Object>> resultExit = this.activitiClientService.submitApply(applySaveRequest);
        if(resultExit.getCode() != 200){
            return ResultUtil.error(ResultEnum.Err_5008);
        }
        EntityBizApply entityBizApply = Convert.convert(EntityBizApply.class,applyRequest);
        entityBizApply.setApplyTime(new Date());
        entityBizApply.setActivitiKey((String)resultExit.getData().get("processInstanceId"));
        entityBizApply.setType(applyRequest.getType());
        if((Boolean)resultExit.getData().get("exit")){
            entityBizApply.setStatus(1);
            EntityBizLeaveApply entityBizLeaveApply=new EntityBizLeaveApply();
            entityBizLeaveApply.setComId(applyRequest.getComId());
            entityBizLeaveApply.setId(applyRequest.getBusinessId());
            entityBizLeaveApply.setStatus(1);
            this.bizLeaveApplyService.update(entityBizLeaveApply.getComId(),entityBizLeaveApply);
        }

//        this.humanClientService.newBizApply(entityBizApply);

        this.bizApplyService.addApply(entityBizApply.getComId(),entityBizApply);

        return ResultUtil.success();
    }

    @PostMapping(CompanyServiceUrl.URL_cancelApply)
    public Result cancelApply(@RequestBody CancelApplyRequest cancelApplyRequest){
        Result<Boolean> result = this.activitiClientService.cancelApply(cancelApplyRequest.getDefKey(),
                cancelApplyRequest.getDefKey()+":"+cancelApplyRequest.getComId()+":"+cancelApplyRequest.getBusinessId());
        if(result.getCode() != 200){
            return ResultUtil.error(ResultEnum.Err_5010);
        }

        EntityBizApply entityBizApply = new EntityBizApply();
        entityBizApply.setComId(cancelApplyRequest.getComId());
        entityBizApply.setBusinessId(cancelApplyRequest.getBusinessId().longValue());
        entityBizApply.setStatus(3);
        entityBizApply.setUpdateTime(new Date());
//        return this.humanClientService.updateBizApply(entityBizApply);
        this.bizApplyService.update(entityBizApply.getComId(),entityBizApply);

        return ResultUtil.success();

    }


//    @PostMapping(CompanyServiceUrl.URL_getApplyListByPid2)
//    public Result getApplyListByPid(@RequestBody GetApplyListByPidRequest getApplyListByPidRequest){
//        EntityBizApply apply = Convert.convert(EntityBizApply.class,getApplyListByPidRequest);
//
//        List<GetApplyListByPidVo> applyListByPidVoList = new ArrayList<>();
////        Result<List<EntityBizApply>> listResult = humanClientService.getApplyListByPid(apply);
//        List<EntityBizApplyExtendVo> listResult =  this.bizApplyService.getApplyListByPid(apply.getComId(), apply);
//        listResult.forEach(entityBizApply -> {
//            GetApplyListByPidVo getApplyListByPidVo = Convert.convert(GetApplyListByPidVo.class,entityBizApply);
//            applyListByPidVoList.add(getApplyListByPidVo);
//        });
//
//        return ResultUtil.success(applyListByPidVoList);
//    }


    private  static void stringToSet(Set<Long> set,Map<Long,String> userMessage,String str,String regex,String content){
        String[] strings = str.split(regex);
        if(strings.length > 0){
            for (String s:strings) {
                Long id = Long.valueOf(s);
                set.add(id);
                userMessage.put(id,content);
            }
        }
    }

}
